package com.geek.novel.global

import android.os.Handler
import android.os.Looper
import android.util.Log
import java.lang.Exception

/**
 * 捕获全局异常的工具类
 */
class GlobalExceptionHandler private constructor() {
    private var debugMode = false
    private var mainCrashHandler: MainCrashHandler? = null
    private var uncaughtCrashHandler: UncaughtCrashHandler? = null
    @Synchronized
    private fun getMainCrashHandler(): MainCrashHandler? {
        if (null == mainCrashHandler) {
            mainCrashHandler = object : MainCrashHandler {
                override fun mainException(t: Thread?, e: Throwable?) {
                }
            }
        }
        return mainCrashHandler
    }

    /**
     * 主线程发生异常时的回调，可用于打印日志文件
     * 注意跨线程操作的可能
     */
    fun setMainCrashHandler(mainCrashHandler: MainCrashHandler): GlobalExceptionHandler {
        this.mainCrashHandler = mainCrashHandler
        return this
    }

    @Synchronized
    private fun getUncaughtCrashHandler(): UncaughtCrashHandler? {
        if (null == uncaughtCrashHandler) {
            uncaughtCrashHandler = object : UncaughtCrashHandler {
                override fun uncaughtException(t: Thread?, e: Throwable?) {

                }
            }
        }
        return uncaughtCrashHandler
    }

    /**
     * 子线程发生异常时的回调，可用于打印日志文件
     * 注意跨线程操作的可能
     */
    fun setUncaughtCrashHandler(uncaughtCrashHandler: UncaughtCrashHandler): GlobalExceptionHandler {
        this.uncaughtCrashHandler = uncaughtCrashHandler
        return this
    }

    private fun isDebugMode(): Boolean {
        return debugMode
    }

    /**
     * debug模式，会打印log日志，且toast提醒发生异常，反之则都没有
     */
    fun setDebugMode(debugMode: Boolean): GlobalExceptionHandler {
        this.debugMode = debugMode
        return this
    }

    /**
     * 完成监听异常的注册
     */
    fun register() {
        //主线程异常拦截
        Handler(Looper.getMainLooper()).post {
            while (true) {
                try {
                    Looper.loop()
                } catch (e: Throwable) {
                    if (isDebugMode()) {
                        Log.e(TAG, "未捕获的主线程异常行为", e)
                    }
					getMainCrashHandler()!!.mainException(Looper.getMainLooper().thread, e)
                }
            }
        }

        //子线程异常拦截
        Thread.setDefaultUncaughtExceptionHandler { t: Thread?, e: Throwable? ->
            if (isDebugMode()) {
                Log.e(TAG, "未捕获的子线程异常行为", e)
            }
            getUncaughtCrashHandler()!!.uncaughtException(t, e)
        }
    }

    interface MainCrashHandler {
        fun mainException(t: Thread?, e: Throwable?)
    }

    interface UncaughtCrashHandler {
        fun uncaughtException(t: Thread?, e: Throwable?)
    }

    companion object {
        private val TAG = GlobalExceptionHandler::class.java.simpleName
        fun getInstance(): GlobalExceptionHandler{
            return GlobalExceptionHandler()
        }
    }
}
